import Song = require("models/song");
import AudioStatus = require("common/audioStatus");

class SongPlayer {
    status = ko.observable<AudioStatus>();
    song = ko.observable<Song>();
    audio: HTMLAudioElement;
    playedTimeText = ko.observable<string>();
    remainingTimeText = ko.observable<string>();
    playedTimePercentage = ko.observable<number>();
    playedSongs = ko.observableArray<Song>();

    private lastPlayedTime = 0;

    constructor() {        
    }

    initialize(audio: HTMLAudioElement) {
        this.audio = audio;
        this.audio.addEventListener("abort", (args) => this.aborted(args));
        this.audio.addEventListener("ended", () => this.status(AudioStatus.Ended));
        this.audio.addEventListener("error", (args) => this.erred(args));
        this.audio.addEventListener("pause", () => this.status(AudioStatus.Paused));
        this.audio.addEventListener("play", () => this.status(AudioStatus.Playing));
        this.audio.addEventListener("playing", () => this.status(AudioStatus.Playing));
        this.audio.addEventListener("waiting", () => this.status(AudioStatus.Buffering));
        this.audio.addEventListener("stalled", (args) => this.stalled(args));
        this.audio.addEventListener("timeupdate", (args) => this.playbackPositionChanged(args));
    }

    playNewSong(song: Song) {
        var currentSong = this.song();
        if (currentSong) {
            this.playedSongs.push(currentSong);
        }

        this.song(song);
        this.playNewUri(song.uri);
    }

    playNewUri(uri: string) {
        this.audio.src = '';
        if (uri) {
            this.audio.src = uri;
            this.audio.load();
            this.audio.play();
        }
    }

    resume() {
        this.audio.play();
    }

    pause() {
        this.audio.pause();
    }

    aborted(args: any) {
        this.status(AudioStatus.Aborted);
        console.log("Audio aborted", this.audio.currentSrc, args);
    }

    erred(args: any) {
        this.status(AudioStatus.Erred);
        console.log("Audio erred", this.audio.currentSrc, args);
    }

    stalled(args: any) {
        this.status(AudioStatus.Stalled);
        console.log("Audio stalled, unable to stream in audio data.", this.audio.currentSrc, args);
    }

    playbackPositionChanged(args: any) {
        var currentTime = this.audio.currentTime;
        var currentTimeFloored = Math.floor(currentTime);
        var currentTimeHasChanged = currentTimeFloored !== this.lastPlayedTime; 
        if (currentTimeHasChanged) {
            this.lastPlayedTime = currentTimeFloored;
            var duration = this.audio.duration;

            var currentPositionDate = new Date().setMinutes(0, currentTimeFloored);
            var currentPosition = moment(<any>currentPositionDate);
            var remainingTimeDate = new Date().setMinutes(0, duration - currentTimeFloored);
            var remainingTime = moment(<any>remainingTimeDate);

            this.playedTimeText(currentPosition.format("m:ss"));
            this.remainingTimeText(remainingTime.format("m:ss"));
            this.playedTimePercentage(Math.floor((100 / duration) * currentTimeFloored));
        }
    }
}

export = SongPlayer;